/*
 * Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
 *
 * Licensed under the Stream License;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.getstream.chat.android.client.api2.model.requests

import com.squareup.moshi.JsonClass
import io.getstream.chat.android.client.api2.model.dto.ExtraDataDto

/**
 * Request body for creating a new poll.
 *
 * @property allow_answers Indicates whether users can suggest user defined answers.
 * @property allow_user_suggested_options Indicates whether users can suggest new options.
 * @property description A description of the poll.
 * @property enforce_unique_vote Indicates whether users can cast multiple votes.
 * @property max_votes_allowed Indicates the maximum amount of votes a user can cast.
 * @property name The name of the poll.
 * @property options The list of options for the poll.
 * @property voting_visibility The visibility of the poll. Accepted values are "public" and "anonymous".
 * @property extraData Any additional custom fields.
 */
@JsonClass(generateAdapter = true)
internal data class CreatePollRequest(
    val allow_answers: Boolean,
    val allow_user_suggested_options: Boolean,
    val description: String,
    val enforce_unique_vote: Boolean,
    val max_votes_allowed: Int,
    val name: String,
    val options: List<UpstreamOptionDto>,
    val voting_visibility: String,
    val extraData: Map<String, Any>,
) : ExtraDataDto {

    internal companion object {
        internal const val VOTING_VISIBILITY_PUBLIC = "public"
        internal const val VOTING_VISIBILITY_ANONYMOUS = "anonymous"
    }
}

/**
 * Request body for updating an existing poll.
 *
 * @property allow_answers Indicates whether users can suggest user defined answers.
 * @property allow_user_suggested_options Indicates whether users can suggest new options.
 * @property description A description of the poll.
 * @property enforce_unique_vote Indicates whether users can cast multiple votes.
 * @property id The id of the poll to update.
 * @property is_closed Indicates whether the poll is closed.
 * @property max_votes_allowed Indicates the maximum amount of votes a user can cast.
 * @property name The name of the poll.
 * @property options The list of options for the poll.
 * @property voting_visibility The visibility of the poll. Accepted values are "public" and "anonymous".
 * @property extraData Any additional custom fields.
 */
@JsonClass(generateAdapter = true)
internal data class UpdatePollRequest(
    val allow_answers: Boolean?,
    val allow_user_suggested_options: Boolean?,
    val description: String?,
    val enforce_unique_vote: Boolean?,
    val id: String,
    val is_closed: Boolean?,
    val max_votes_allowed: Int?,
    val name: String,
    val options: List<UpstreamOptionDto>?,
    val voting_visibility: String?,
    val extraData: Map<String, Any>,
) : ExtraDataDto

/**
 * Model representing a poll option to be sent upstream.
 *
 * @property id the id of the option. If not provided, it will be generated by the server.
 * @property text the text of the option.
 * @property extraData any additional custom fields.
 */
@JsonClass(generateAdapter = true)
internal data class UpstreamOptionDto(
    val id: String? = null,
    val text: String,
    val extraData: Map<String, Any>,
) : ExtraDataDto

/**
 * Used for voting on a poll.
 *
 * @property vote the vote object.
 */
@JsonClass(generateAdapter = true)
internal data class PollVoteRequest(
    val vote: UpstreamVoteDto,
)

/**
 * Used for updating a poll.
 *
 * @property set the fields to set.
 * @property unset the fields to unset.
 */
@JsonClass(generateAdapter = true)
internal data class PartialUpdatePollRequest(
    val set: Map<String, Any> = emptyMap(),
    val unset: List<String> = emptyList(),
)

/**
 * Used for voting on a poll.
 *
 * @property option_id the text of the answer.
 */
@JsonClass(generateAdapter = true)
internal data class UpstreamVoteDto(
    val option_id: String? = null,
    val answer_text: String? = null,
)
